
#define LOG_LOCATION QString("%1:%2").arg(__FILE__).arg(__LINE__)

// 修改日志宏定义，添加类别参数

#define LOG_CAMERA(msg)    writeLog(CAMERA_LOG, "INFO", LOG_LOCATION, msg, true) // 显示在主日志框
#define LOG_CAMERAPS(msg)  writeLog(CAMERAPS_LOG, "INFO", LOG_LOCATION, msg, true)
#define LOG_TEMP_VAC(msg)  writeLog(TEMP_VACUUM_LOG, "INFO", LOG_LOCATION, msg, false)

#define LOG_ALARM(msg)     writeLog(ALARM_LOG, "INFO", LOG_LOCATION, msg, false)
#define LOG_GENERAL(msg)   writeLog(GENERAL_LOG, "INFO", LOG_LOCATION, msg, false)

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTimer>
#include <QTcpServer>
#include <QTcpSocket>
#include <QUdpSocket>

#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>

#include <QtCharts>
#include <QMap>
#include <QJsonDocument>
#include <QJsonObject>
#include <QVector>
#include <QProcess>
#include <QDir>
#include <QLogValueAxis>
#include <QtConcurrent/QtConcurrent>
#include <QFuture>
#include "fitsconverter.h"
#include "configmanager.h"
#include <memory>
#include <vector>
#include <fstream>
#include <QTextStream>

#include <QElapsedTimer>

#include "exposure.h"
#include "Alarm.h"
#include "hardware_status.h"
#include "camera_enmu.h"
#include "led.h"
#include "camera_states.h"

// #include "ui_mainwindow.h"


QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    void threadSafeLog(const QString& level, const QString& message);


private slots:
    //test c++ bin2fits
    void on_btnbin2fits_clicked();

    void handleNewConnection();
    void readClientData();
    void clientDisconnected();
    void processMCUData();

    void onbtnReadTemp();
    //void onbtnReadVacuum();

    void onSetTemperature();

    void updateVacuumData();
    void updateCameraStatus();
    void updateTemperatureData(); // 专门更新温度数据
    void updateTemperatureCurves(); // 专门控制曲线显示
    void updateTemperatureDisplay();   // 更新多标签
    void clearOldData();
    void updateExposureProgress(); //更新曝光进度条

    void on_btnsetmcu_clicked();
    void on_btnsetcamera_clicked();

    // 新增槽函数
    void processCameraResponse();


    void on_btnSetReadoutRate_clicked();
    void on_btnStartExposure_clicked();
    void on_btnAbort_clicked();
    void on_btnBrowsePath_clicked();
    void on_btnPowerDown_clicked();
    void on_btnPowerOn_clicked();
    void on_btnShutterOff_clicked();
    void on_btnShutterOn_clicked();
    void on_btnCameraPowerOff_clicked();
    void on_btnCameraPowerOn_clicked();
    void on_btnHeatPowerOff_clicked();
    void on_btnHeatPowerOn_clicked();
    void on_btnVaccuPowerOff_clicked();
    void on_btnVaccuPowerOn_clicked();
    void on_btnReadIOStatus_clicked();
    //连拍功能相关槽函数
    void on_btnStartSequence_clicked();
    void on_btnStopSequence_clicked();
    void onSequenceFinished();
    void sequenceFinished();  // 序列完成时的处理函数
    void processSequenceNextFrame();

    void on_btnSetFitsPath_clicked();
    //日志相关槽函数
    //void onSetLogDirClicked();

    void onSendCameraCommand();
    void onSendTempCommand();
    //link to camera
    void onLinkToCameraClicked();
    void updateHeartbeatStatus();

    void updateTempChartTimeRange(int minutes);   // 温度图时间范围更新
    void updateVacuumChartTimeRange(int minutes); // 真空度图时间范围更新

    //void on_btnSetCameraIp_clicked();
    void on_btnmergefits_clicked();

    void onCheckboxShowFitsToggled(bool checked);

    void resetImageCounter();

    //void togglePowerControl(bool checked);
    void setupPowerControlUI();

    void onLoopCheckBoxStateChanged(int state);

    //void processNextLoop();


    //void updateCameraStatus();
    void querySlaveStatus();

    void checkSlaveTimeout(); // 新增超时检测

    void onHistorySelected(int index);

    void updatePowerButtonStates(QPushButton* onBtn, QPushButton* offBtn, bool isOn);

    void showNetworkConfigDialog();
signals:
    void setTemperatureRequested(double temp); // 线程安全信号

private:
    Ui::MainWindow *ui;

    //历史拍摄任务的下拉菜单
    QComboBox* m_historyComboBox;
    QVector<QStringList> m_shootingHistory; // 存储历史记录[文件名, 路径, 日期]
    void recordShootingHistory(const QString& fitsName, const QString& fitsPath);
    void updateHistoryComboBox();
    void saveHistoryToFile();
    void loadHistoryFromFile();

    ledStatus statusLeds;

    void initStatusLeds();
    void sendCommandToSlave(const QString& cmd, const QString& ip);
    void updateMasterLedStatus(bool isConnected);
    void processSlaveStatus(const QString &response);
    // 状态监测相关
    QTimer* m_statusCheckTimer;
    QHash<QString, qint64> m_lastStatusTime; // 存储最后收到状态的时间戳
    QHash<QString, bool> m_slaveBoardStatus; // 从板状态(00-03)

    void checkCameraConnectionStatus();
    void checkMCUConnectionStatus();
    void updateConnectionUI();
    void updateCameraControls(bool isExposing);

    //添加电源控制相关成员
    QToolButton* powerToolButton;
    QMenu* powerMenu;
    QWidget* powerControlWidget;
    // 电源控制界面上的按钮
    QPushButton* btnCameraPowerOn;
    QPushButton* btnCameraPowerOff;
    QPushButton* btnHeatPowerOn;
    QPushButton* btnHeatPowerOff;
    QPushButton* btnVaccuPowerOn;
    QPushButton* btnVaccuPowerOff;
    QMenu* createPowerSubMenu(const QString& title, const QString& iconPath);

    QTcpServer *tcpServer;
    QMap<QString, QTcpSocket*> clientSockets;
    QUdpSocket *mcuSocket;
    int serverPort = 9076;
    QString mcuIp;
    int mcuPort;
    QMutex logMutex;
    QMutex fitsMutex;

    int m_localImageCounter = 0; // 用于本地拍摄的图片计数器

    int firstdoneflag = 0;


    ExposurePhase currentPhase = PHASE_IDLE;

    struct PendingResponse {
        QTcpSocket* client;
        QString camId;
        double expTime;
        QString expStartTimeStr;
        QString imageName;

        bool isValid() const {
            return client != nullptr && !camId.isEmpty();
        }
    };

    PendingResponse m_pendingResponse; // key为tag
    ExposureInfo m_currentExpInfo;

    QDateTime parseCameraTimestamp(const QString& timestampStr);
    void processCameraHeader(const QString& response);
    void updateFitsHeaderWithTimestamps(const QString& fitsPath,
                                        const QDateTime& expStart,
                                        const QDateTime& expEnd,
                                        const QDateTime& readoutStart);

    QMutex m_fitsMutex; // 用于CFITSIO操作同步

    QThreadPool m_threadPool; // 线程池
    // 辅助函数：提取 MCU 命令（复用现有逻辑）
    QString extractMcuCommand(const QString &ocsCommand);

   // int timeCounter = 0;
    QList<QPair<QDateTime, double>> tempDataPoints;  // 存储温度数据点(时间,值)
    QList<QPair<QDateTime, double>> vacuumDataPoints; // 存储真空度数据点(时间,值)

    void initializeFromConfig();

    QTimer* m_alarmCheckTimer;  // 报警检查定时器

    AlarmStatus alarmStatus;

    void updateAlarmUI();
    void logAlarms();
    void checkAllAlarms();
    // 添加获取传感器值的函数
    double getCurrentValue(const QString& sensorName) const;

    QTimer *m_connectionCheckTimer;
    struct HardwareStatus hwStatus;

    //定时器
    // QTimer *autoUpdateTimer;   //温度\真空度更新定时器
    // 温度曲线复选框相关
    QMap<QString, QCheckBox*> tempCheckBoxes; // 存储测温点复选框
    QGroupBox* tempCheckBoxGroup; // 复选框容器
    void modifyCameraStatusFile(bool powerOn);
    // 相机通信相关
    QString currentTag; // 当前拍摄标记
    //QString binFilePath; // BIN文件存储路径
    int frameDoneCount = 0;  // 用于计数收到的done响应

    QSet<QString> m_receivedTags; // 用于记录已接收的tag

    int frameDoneCount_00 = 0;
    int frameDoneCount_01 = 0;
    int frameDoneCount_02 = 0;
    int frameDoneCount_03 = 0;
    //QString currentTag;      // 当前曝光任务的唯一标识

    // Python脚本路径
    QString pythonPath = "python";
    QString binToFitsScript = "bin2fits.py";
    //添加C++ BIN2FITS转换方法
    bool convertBinToFits(const QString& binPath,
                          const QString& fitsPath,
                          const QString& baseFilename,
                          const std::vector<std::pair<std::string, std::string>>& keywords = {});
    // 心跳相关
    QTimer m_heartbeatTimer;
    QDateTime m_lastHeartbeatTime;
    QString m_localIp;
    quint16 m_localPort = 11001; // ICS默认监听端口
    bool m_isRegistered = false;

    //相机相关
    QUdpSocket *cameraSocket;
    QString cameraIp;
    int cameraPort;
    QString binPath;

    CameraStates cameraState;
    void handleStatusResponse(const QString &response);
    void handleFrameDone(const QString &responses);
    void sendCameraCommand(const QString &cmd);
    void resetFrameCounter();
    // 读出速度映射表
    const QMap<int, QString> readoutRateMap = {
        {0, "2M"},
        {1, "1M"},
        {2, "512K"},
        {3, "256K"}
    };
    // 检查相机是否空闲
    bool isCameraIdle() const {
        return cameraState.status == 0; // 0表示空闲状态
    }
    void handleReadoutRateResponse(const QString &response);
    int m_successCount = 0; // 成功响应计数器

    // 进度条相关
    QTimer *progressTimer;
    qint64 progressStartTime = 0;
    int currentProgressTotalTime = 0; // 当前任务总时间(曝光时间+10秒)
    double currentExposureTime = 0;      // 当前曝光时间(秒)

    // 连续拍摄相关
    struct SequenceTask {
        QString filename;
        double expTime;
        bool dark;
        bool pinning;
        bool dump;
    };
    QString fitsSavePath;  // 存储FITS文件保存路径
    // 添加状态标志
    bool m_sequenceAborted = false;


    QVector<SequenceTask> sequenceTasks;
    int currentSequenceIndex = -1;
    bool isSequenceRunning = false;
    QTimer *sequenceTimer;
    QString sequenceSavePath;
    QString currentSequenceName; // 用于存储当前序列名称
    // 新增成员变量
    QString currentBaseFilename; // 用户输入的基础文件名
    QMap<QString, QString> binToFitsMap; // 存储bin文件与fits文件的映射关系

    std::vector<std::pair<std::string, std::string>> collectManualHeaderInfo();// 收集手动拍摄的头信息
    std::vector<std::pair<std::string, std::string>> m_manualKeywords; // 存储手动拍摄的头信息
    bool updateFitsHeader(const QString& fitsPath, const QJsonObject& headerData);//向已存在的FITS文件添加头信息
    double calculateFitsMedian(const QString& fitsPath);//计算图像中值（仅对平场类型）
    bool mergeFitsFiles(const QStringList& inputFiles, const QString& outputFile);

    void launchDS9(const QString& fitsPath);
    QString ds9Path = "/usr/bin/ds9"; // DS9默认路径
    bool detectDS9();
    QScopedPointer<QProcess> ds9Process;

    //// 日志相关成员
    QString m_logDirectory;
    QFile m_logFile;
    QDateTime m_startTime;
    QTimer m_logTimer;  // 用于定时写入日志
    QTextStream m_logStream;                 // 文件写入流（提高性能）
    //QTimer m_logFlushTimer;                  // 定时刷新文件缓冲区
    QString m_logPath; // 日志文件路径
    QFile m_autoUpdateLogFile;  // 自动更新专用日志文件
    QString m_autoUpdateLogPath ; // 自动更新日志路径
    void writeAutoUpdateLog(const QString &message); // 自动更新日志写入方法
    // 日志方法
    void initializeLogSystem();
    //void writeLog(const QString& message);
    //void writeLog(const QString& level, const QString& location, const QString& message);
    void writeLog(LogCategory category, const QString& level, const QString& location, const QString& message, bool showInUI);
    void writeLogx(LogCategory category, const QString& level,
                               const QString& location, const QString& message,
                               bool showInUI);
    void checkAndRotateLogFiles();

    // 替换原有的日志文件相关成员
    QMap<LogCategory, QFile*> m_logFiles;
    QMap<LogCategory, QTextStream*> m_logStreams;
    QMutex m_logMutex;
    // 日志刷新定时器
    QTimer m_logFlushTimer;

    QTimer *dataUpdateTimer;
    QTimer *exposureTimer;
    QTimer *vacuumCheckTimer;

    QChart *tempChart;
    QtCharts::QLineSeries *tempSeries;
    QChart *vacuumChart;
    QtCharts::QLineSeries *vacuumSeries;
    void parseCameraStatus(const QString &status);

    void initializeNetwork();
    void initializeUI();
    void initializeCharts();

    void parseProtocol(const QString &command, QTcpSocket *client);
    void handleCommand300(const QMap<QString, QString> &params, QTcpSocket *client);
    void handleCommand301(const QMap<QString, QString> &params, QTcpSocket *client);
    void handleCommand302(const QMap<QString, QString> &params, QTcpSocket *client);
    void handleCommand303(const QMap<QString, QString> &params, QTcpSocket *client);
    void handleCommand304(const QMap<QString, QString> &params, QTcpSocket *client);
    void handleCommand305(const QMap<QString, QString> &params, QTcpSocket *client);
    void handleCommand306(const QMap<QString, QString> &params, QTcpSocket *client);
    void handleCommand307(const QMap<QString, QString> &params, QTcpSocket *client);
    void handleCommand308(const QMap<QString, QString> &params, QTcpSocket *client);

    void sendResponse(const QString &response, QTcpSocket *client);
    void handleClientError(QTcpSocket *client);
    void sendCommand(const QString &cmd);
    void sendCommandToMCU(const QString &cmd, bool isAutoUpdate = false);
    void logToBoth(const QString &message);
    void updateCameraParameters(const QJsonObject &config);
    void checkVacuumAlert();
    QString formatTemperature(double temp);

    // 网络访问管理器
    QNetworkAccessManager* m_networkManager;

    // 报警推送方法
    void sendAlarmToServer(const QString& alarmName);
    int getModuleCode(const QString& alarmName);
    QString getAlarmReason(const QString& alarmName);
    void initializeAlarmThresholds();
    void checkAlarmRecovery();
    void sendRecoveryToServer(const QString& alarmName);

    // 服务器配置
    QString m_alertServerUrl;
    QString m_alertServerToken;
    int m_alertServerTimeout;
};


#endif // MAINWINDOW_H
